package completablefuture;

import org.junit.Test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class UseCompletableFuture {

    /**
     * 1.thenApply可以接受上一个任务的返回结果并继续添加结果返回
     * 2.thenApply无法处理异常上一个任务出现异常的话它不会继续执行
     * 3.CompletableFuture.allOf(a, b).join() 同步
     */
    @Test
    public void test05()   {
        CompletableFuture<String> a = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            int n = 5 / 0;
            return "a";
        }).thenApply(e -> {
            System.out.println(Thread.currentThread().getName());
            return e + "bcde";
        });

        CompletableFuture<String> b = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return "1";
        }).thenApply(e -> {
            System.out.println(Thread.currentThread().getName());
            return e + "2345";
        });

        // 同步等待所有的异步任务都完成才执行
        CompletableFuture.allOf(a, b).join();

        try {
            System.out.println(a.get()+" "+b.get());
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    /**
     * Integer i = future.get(); 不会阻塞
     * 因为和test02的区别是原生future没有whenCompleteAsync操作
     *
     * 1.future.get()拿到的是50而非100
     * 2.future.get()不会阻塞, future2才会阻塞
     * 3.whenComplete()不能添加返回值但可以处理异常对象
     * 4.handle()可以添加返回值也可以处理异常对象
     *
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void test03() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            System.out.println("50 start");
            int i = 5 / 0;
            return 50;
        });

        CompletableFuture<Integer> future2 = future.handle((t, u) -> {
            System.out.println(Thread.currentThread().getName());
            if(u != null){
                u.printStackTrace();
                return 0;
            }
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                System.out.println(e.getMessage());
            }
            return t + 50;
        });
        Integer i = future2.get(); // 不阻塞
        System.out.println(Thread.currentThread().getName() + " get i:" + i);
    }

}
